package com.opennews.openplatform.myspringbootcore.util;

import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

public class SharedUtil {
    private static final Random random = new Random();

    /**
     * Check if the itemId string is empty.
     *
     * @param input The itemId string.
     * @return True means the itemId string is empty. False means NOT.
     */
    public static boolean isEmpty(String input) {
        return input != null && input.trim().isEmpty();
    }

    /**
     * Check if the itemId string is null or empty.
     *
     * @param input The itemId string.
     * @return True means the itemId string is null or empty. False means NOT.
     */
    public static boolean isNullOrEmpty(String input) {
        return input == null || input.trim().equalsIgnoreCase("null") || isEmpty(input);
    }

    public static String convertSnakeToCamel(String snakeCaseString) {
        if (isNullOrEmpty(snakeCaseString)) {
            return snakeCaseString;
        }

        Pattern pattern = Pattern.compile("_(.)");
        Matcher matcher = pattern.matcher(snakeCaseString);

        return matcher.replaceAll(m -> m.group(1).toUpperCase());
    }

    public static String convertCamelToSnake(String camelCaseString) {
        if (camelCaseString == null || camelCaseString.isEmpty()) {
            return camelCaseString;
        }

        // Uses regex to match boundaries and insert underscores.
        return camelCaseString
                .replaceAll("([a-z])([A-Z])", "$1_$2")      // Adds underscore before uppercase letters
                .toLowerCase();                                                // Converts the entire string to lowercase
    }


    /**
     * Gets the next random double value in the provided range.
     *
     * @param min The min double value.
     * @param max The max double value.
     * @return The random double in the provided range.
     */
    public static double nextRandomDoubleInRange(double min, double max) {
        if (min >= max) {
            throw new IllegalArgumentException("Min must be less than max");
        }

        double range = max - min;
        double scaled = random.nextDouble() * range;

        return scaled + min;
    }

    /**
     * Gets the next random int value in provided range
     *
     * @param min: The min int value
     * @param max: The max int value
     * @return The random int in the provided range
     */
    public static int nextRandomIntInRange(int min, int max) {
        return (int) nextRandomDoubleInRange(min, max);
    }

    /**
     * Maps the provided map stream to a stream with the value based on the key.
     *
     * @param source: The map stream.
     * @param key:    The map key which value will be mapped to a new stream.
     * @return The new stream which contains the data from the source.
     */
    public static <T> Stream<T> mapListMap(Stream<Map<String, Object>> source, String key) {
        return source.map(map -> (T) map.get(key));
    }
}
